package de.tu_darmstadt.gdi1.xcom.tests.testcases.students;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel3;

/**
 * 
 * Tests if savegames are correctly interpreted
 * 
 * @author Lukas Schwoebel
 *
 */
public class DoorSwitchTest {
	
	private XcomTestAdapterLevel3 testAdapter;
	
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testAdapter = new XcomTestAdapterLevel3();
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel3#isDoorOpen()}.
	 */
	@Test
	public final void testOpenDoor() {
				
		// load savegame
		testAdapter.loadLevelFromString(TestLevel.testLevel);
		
		// default state, door is closed
		assertFalse("The door at 8:4 should be closed at the beginning", testAdapter.isDoorOpen(8, 4));
		
		// move player 2:5 to switch and use it
		testAdapter.changeActivePlayer(2, 5);
		testAdapter.rotateActivePlayer(false);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		
		assertTrue("The door at 8:4 should be opened after using the switch", testAdapter.isDoorOpen(8, 4));		
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#actionPointsLeft()}.
	 */
	@Test
	public final void testActionPointsForSwitchUsage() {
				
		// load savegame
		testAdapter.loadLevelFromString(TestLevel.testLevel);
		
		// default state, door is closed
		assertFalse("The door at 8:4 should be closed at the beginning", testAdapter.isDoorOpen(8, 4));
		
		// move player 2:5 to switch and use it
		testAdapter.changeActivePlayer(2, 5);
		testAdapter.rotateActivePlayer(false);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		
		assertEquals("The player at former position 2:5 (moved to 1:5) should have 70 actionpoints now", 70, testAdapter.actionPointsLeft());
		
		// now use the switch several times, should not cost any actionpoints
		testAdapter.performActionForActivePlayer();		
		assertTrue("The door at 8:4 should be opened after using the switch", testAdapter.isDoorOpen(8, 4));
		assertEquals("Using the switch should not cost any actionpoints, still 70 AP should be left", 70, testAdapter.actionPointsLeft());
		// just to be sure, no healthpoints left either
		assertEquals("Using the switch should not cost any healthpoints", 50, testAdapter.healthPointsLeft());
		
		// second time
		testAdapter.performActionForActivePlayer();		
		assertFalse("The door at 8:4 should be opened after using the switch", testAdapter.isDoorOpen(8, 4));
		assertEquals("Using the switch should not cost any actionpoints, still 70 AP should be left", 70, testAdapter.actionPointsLeft());
		
		// third time
		testAdapter.performActionForActivePlayer();		
		assertTrue("The door at 8:4 should be opened after using the switch", testAdapter.isDoorOpen(8, 4));
		assertEquals("Using the switch should not cost any actionpoints, still 70 AP should be left", 70, testAdapter.actionPointsLeft());
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#elementOnPosition()}.
	 */
	@Test
	public final void testMovingIntoDoor() {
				
		// load savegame
		testAdapter.loadLevelFromString(TestLevel.testLevel);
		
		// default state, door is closed
		assertFalse("The door at 8:4 should be closed at the beginning", testAdapter.isDoorOpen(8, 4));
		
		// move player 2:5 to switch and use it
		testAdapter.changeActivePlayer(2, 5);
		testAdapter.rotateActivePlayer(false);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		
		// save the savegame as we use it several times
		String saveGameDoorOpen = testAdapter.returnGamestateAsSavegame();

		// new state, door is open
		assertTrue("The door at 8:4 should be open after using switch", testAdapter.isDoorOpen(8, 4));
		
		// First test, walk with human into door and then close the door
		
		// now walk with human into the door, should be possible
		testAdapter.changeActivePlayer(4, 6);
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		testAdapter.performActionForActivePlayer();
		testAdapter.performActionForActivePlayer();
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(false);
		testAdapter.performActionForActivePlayer();
		assertEquals("Walking with player at (former) position 4:6 should cost 17 AP", 58, testAdapter.actionPointsLeft());
		// check if walking into door is possible and cost 3 AP
		testAdapter.performActionForActivePlayer();
		assertEquals("Walking into the open door should cost 3 AP", 55, testAdapter.actionPointsLeft());
		assertEquals("The player should now be in the open door", '@', testAdapter.elementOnPosition(8, 4));
		assertEquals("The player should now be in the open door", '.', testAdapter.elementOnPosition(8, 5));
		// now close the door, human should die and door should be closed
		testAdapter.changeActivePlayer(1, 5);
		testAdapter.performActionForActivePlayer(); // close door
		// now there should be a door-element again
		assertEquals("After closing the door at 8:4, the human should disappear/die", '=', testAdapter.elementOnPosition(8, 4));
		// now check if we can change to former player at 8:4 (identified by AP = 55)
		testAdapter.changeActivePlayer(8, 4);
		assertNotSame("The player at 8:4 should have been killed, not possible to change to this player!", 55, testAdapter.actionPointsLeft());
		// check in gamestate/savegame for existence
		assertTrue("The player at 8:4 should have been killed, do not list in savegame!",
				(testAdapter.returnGamestateAsSavegame().indexOf("//@;8;4;n;50;55;50;50;10\n") < 0));
		
		
		// Second test, walk with alien into door
		testAdapter.loadLevelFromString(saveGameDoorOpen);
		testAdapter.performKIAction("7;5;r");
		testAdapter.performKIAction("7;5;f");
		testAdapter.performKIAction("8;5;l");
		// check if walking into door costs the same for the KI
		assertTrue("Alien should have 70 actionpoints before walking into door",
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;8;5;n;50;70;50;") >= 0));
		// now walk into door
		testAdapter.performKIAction("8;5;f");
		assertEquals("The alien should be able to walk into the open door", 'Z', testAdapter.elementOnPosition(8, 4));
		assertEquals("The alien should be able to walk into the open door", '.', testAdapter.elementOnPosition(8, 5));
		// check if walking into door costs the same for the KI
		assertTrue("Alien should have 67 actionpoints after walking into door",
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;8;4;n;50;67;50;") >= 0));
		// now close the door and the alien should disappear
		// first, end turn
		testAdapter.endTurn();
		testAdapter.changeActivePlayer(1, 5);
		testAdapter.performActionForActivePlayer();
		assertFalse("Door should be closed now", testAdapter.isDoorOpen(8, 4));
		assertEquals("After closing the door, the alien should disappear", '=', testAdapter.elementOnPosition(8, 4));
		assertTrue("After closing the door, the alien should disappear/die and not be listed in savegame any more!",
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;8;4;n;50;67;50;50;0\n") < 0));
		
	}
}
